/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.chartsy.stochf;
import com.tictactec.ta.lib.Core;
import com.tictactec.ta.lib.MAType;
import com.tictactec.ta.lib.MInteger;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.text.DecimalFormat;
import java.util.LinkedHashMap;
import org.chartsy.main.ChartFrame;
import org.chartsy.main.chart.Indicator;
import org.chartsy.main.data.DataItem;
import org.chartsy.main.data.Dataset;
import org.chartsy.main.utils.DefaultPainter;
import org.chartsy.main.utils.Range;
import org.chartsy.main.utils.SerialVersion;
import org.chartsy.talib.TaLibInit;
import org.chartsy.talib.TaLibUtilities;
import org.openide.nodes.AbstractNode;
/**
*
* @author joshua.taylor
*/
public class StochF extends Indicator
{
private static final long serialVersionUID = SerialVersion.APPVERSION;
private static String FULL_NAME = "Stochastic Fast";
public static final String SLOWD = "slow%D";
public static final String SLOWK = "slow%K";
public static final String FASTD = "fast%D";
public static final String FASTK = "fast%K";
private IndicatorProperties properties;
//variables for TA-Lib utilization
private int lookback;
private double[] outputFastD;
private double[] outputFastK;
private transient MInteger outBegIdx;
private transient MInteger outNbElement;
private transient Core core;
//variables specific to this indicator
private int periodD;
private int periodK;
private double[] allHighs;
private double[] allLows;
private double[] allClose;
//the next variable is used for holding the newly calculated data
private Dataset calculatedDatasetFastD;
private Dataset calculatedDatasetFastK;
public StochF()
{
super();
properties = new IndicatorProperties();
}
@Override
public String getName(){ return FULL_NAME; }
@Override
public String getLabel()
{ return properties.getLabel() + " (" + properties.getPeriodK() + ", " + properties.getSmooth() + ", " + properties.getPeriodD() + ")"; }
@Override
public String getPaintedLabel(ChartFrame cf)
{ return (properties.getSF() ? "Fast" : "Slow") + getLabel(); }
@Override
public Indicator newInstance(){ return new StochF(); }
@Override
public LinkedHashMap getHTML(ChartFrame cf, int i)
{
LinkedHashMap ht = new LinkedHashMap();
DecimalFormat df = new DecimalFormat("#,##0.00");
double[] values = getValues(cf, i);
String[] labels = {"%D:", "%K:"};
ht.put((properties.getSF() ? "Fast" : "Slow") + getLabel(), " ");
if (values.length > 0) {
Color[] colors = getColors();
for (int j = 0; j < values.length; j++) {
ht.put(getFontHTML(colors[j], labels[j]),
getFontHTML(colors[j], df.format(values[j])));
}
}
return ht;
}
@Override
public Range getRange(ChartFrame cf){ return new Range(0, 100); }
@Override
public void paint(Graphics2D g, ChartFrame cf, Rectangle bounds)
{
Dataset stoD = visibleDataset(cf, properties.getSF() ? FASTD : SLOWD);
Dataset stoK = visibleDataset(cf, properties.getSF() ? FASTK : SLOWK);
if (stoD != null && stoK != null)
{
if (maximized)
{
Range range = getRange(cf);
DefaultPainter.line(g, cf, range, bounds, stoD, properties.getColorD(), properties.getStrokeD());
DefaultPainter.line(g, cf, range, bounds, stoK, properties.getColorK(), properties.getStrokeK());
}
}
}
@Override
public boolean hasZeroLine(){ return false; }
@Override
public boolean getZeroLineVisibility(){ return false; }
@Override
public Color getZeroLineColor(){ return null; }
@Override
public Stroke getZeroLineStroke(){ return null; }
@Override
public boolean hasDelimiters(){ return true; }
@Override
public boolean getDelimitersVisibility(){ return true; }
@Override
public double[] getDelimitersValues(){ return new double[] {20d, 50d, 80d}; }
@Override
public Color getDelimitersColor(){ return properties.getDelimiterColor(); }
@Override
public Stroke getDelimitersStroke(){ return properties.getDelimiterLineStroke(); }
@Override
public Color[] getColors()
{ return new Color[] {properties.getColorD(), properties.getColorK()}; }
@Override
public double[] getValues(ChartFrame cf)
{
Dataset stoD = visibleDataset(cf, properties.getSF() ? FASTD : SLOWD);
Dataset stoK = visibleDataset(cf, properties.getSF() ? FASTK : SLOWK);
if (stoD != null && stoK != null)
return new double[] {stoD.getLastClose(), stoK.getLastClose()};
return new double[] {};
}
@Override
public double[] getValues(ChartFrame cf, int i)
{
Dataset stoD = visibleDataset(cf, properties.getSF() ? FASTD : SLOWD);
Dataset stoK = visibleDataset(cf, properties.getSF() ? FASTK : SLOWK);
if (stoD != null && stoK != null)
return new double[] {stoD.getCloseAt(i), stoK.getCloseAt(i)};
return new double[] {};
}
@Override
public boolean getMarkerVisibility(){ return properties.getMarker(); }
@Override
public AbstractNode getNode(){ return new IndicatorNode(properties); }
@Override
public Double[] getPriceValues(ChartFrame cf)
{ return new Double[] {new Double(20), new Double(50), new Double(80)}; }
@Override
public void calculate()
{
Dataset initial = getDataset();
int count = 0;
if (initial != null && !initial.isEmpty())
count = initial.getItemsCount();
/**********************************************************************/
//This entire method is basically a copy/paste action into your own
//code. The only thing you have to change is the next few lines of code.
//Choose the 'lookback' method and appropriate 'calculation function'
//from TA-Lib for your needs. Everything else should stay basically the
//same
//prepare ta-lib variables
outputFastD = new double[count];
outputFastK = new double[count];
outBegIdx = new MInteger();
outNbElement = new MInteger();
core = TaLibInit.getCore();//needs to be here for serialization issues
//[your specific indicator variables need to be set first]
periodK = properties.getPeriodK();
periodD = properties.getPeriodD();
allHighs = initial.getHighValues();//new double[count];
allLows = initial.getLowValues();//new double[count];
allClose = initial.getCloseValues();//new double[count];
//now do the calculation over the entire dataset
//[First, perform the lookback call if one exists]
//[Second, do the calculation call from TA-lib]
lookback = core.stochFLookback(periodK, periodD, MAType.Sma);
core.stochF(0, count-1, allHighs, allLows, allClose, periodK, periodD, MAType.Sma, outBegIdx, outNbElement, outputFastK, outputFastD);
//Everything between the /***/ lines is what needs to be changed.
//Everything else remains the same. You are done with your part now.
/**********************************************************************/
//fix the output array's structure. TA-Lib does NOT match
//indicator index and dataset index automatically. That's what
//this function does for us.
outputFastD = TaLibUtilities.fixOutputArray(outputFastD, lookback);
outputFastK = TaLibUtilities.fixOutputArray(outputFastK, lookback);
calculatedDatasetFastD = Dataset.EMPTY(initial.getItemsCount());
for (int i = 0; i < outputFastD.length; i++)
calculatedDatasetFastD.setDataItem(i, new DataItem(initial.getTimeAt(i), outputFastD[i]));
calculatedDatasetFastK = Dataset.EMPTY(initial.getItemsCount());
for (int i = 0; i < outputFastK.length; i++)
calculatedDatasetFastK.setDataItem(i, new DataItem(initial.getTimeAt(i), outputFastK[i]));
addDataset(FASTD, calculatedDatasetFastD);
addDataset(FASTK, calculatedDatasetFastK);
}
}